package org.wanda.pv.controller.file;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFPictureData;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.filepool.NutFilePool;
import org.nutz.ioc.impl.PropertiesProxy;
import org.nutz.lang.Files;
import org.nutz.lang.random.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.wanda.pv.framework.base.Result;
import org.wanda.pv.framework.constant.AttachmentType;
import org.wanda.pv.framework.utils.CompareUtil;
import org.wanda.pv.framework.utils.StringUtil;
import org.wanda.pv.model.business.Attachment;
import org.wanda.pv.model.file.FileUploadInfo;
import org.wanda.pv.model.file.PersistFile;
import org.wanda.pv.model.file.TempFile;
import org.wanda.pv.model.hy.HyDrawing;
import org.wanda.pv.model.hy.HyUserInfo;
import org.wanda.pv.service.business.MarkFileReService;
import org.wanda.pv.service.conver.PDFConverImage;
import org.wanda.pv.service.file.FileUploadService;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/file")
@SuppressWarnings("all")
public class FileUploadController {
    private final Log logger = LogFactory.getLog(this.getClass());

    @Autowired
    private Dao dao;

    @Autowired
    private FileUploadService fileUploadService;

    @Autowired
    private MarkFileReService markFileReService;

    @Autowired
    private NutFilePool tempFilePool;

    @Autowired
    private PDFConverImage pdfConverImage;

    private static InputStream resourceAsStream = FileUploadController.class.getClassLoader().getResourceAsStream("application.properties");
    private static PropertiesProxy pp = new PropertiesProxy(resourceAsStream);
    public static String IMG_URL = pp.get("img_url");



    @RequestMapping("/imageLoader")
    public void imageLoader(HttpServletRequest request, HttpServletResponse response,Long attachmentId)throws ServletException, IOException{
        OutputStream img = response.getOutputStream();
        InputStream fis = getFileInputStream(attachmentId); // docx file input stream
        if(fis != null) {
            String imageId = request.getParameter("imageId");
            XWPFDocument document = new XWPFDocument(fis); // load document
            XWPFPictureData pic = document.getPictureDataByID(imageId);// get picture
            String ext = imageId.substring(imageId.lastIndexOf(".") + 1);
            response.setContentType("image/" + ext);// set correct content type according to file type ServletOutputStream
            if (pic != null)
                img.write(pic.getData());
            else {
                List<XWPFPictureData> pics = document.getAllPictures();
                for (XWPFPictureData p : pics) {
                    if (imageId.equals(p.getFileName())) {
                        img.write(p.getData());
                        break;
                    }
                }
            }
        }


    }

    private InputStream getFileInputStream(Long attachmentId) throws FileNotFoundException {
        Attachment attachment = dao.fetch(Attachment.class, attachmentId);
        return new FileInputStream(attachment.getServerPath());
    }

    @RequestMapping("/download")
    public void download(Long id,HttpServletResponse response) throws Exception{
        BufferedInputStream bis = null;

        OutputStream os = null;
        File file = null;

        HyDrawing hyDrawing = dao.fetch(HyDrawing.class, id);
        Long pfid = hyDrawing.getPfid();
        URL url = null;
        String fileName = hyDrawing.getFileName();
        fileName = URLEncoder.encode(fileName,"UTF-8");
        response.setContentType("application/x-download; charset=utf-8");
        response.setHeader("Content-Disposition", "attachment;fileName="+fileName);
        if (pfid==null){
            url =  new URL(hyDrawing.getFilePath());
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();//利用HttpURLConnection对象,我们可以从网络中获取网页数据.
            conn.setDoInput(true);
            conn.connect();
            bis = new BufferedInputStream(conn.getInputStream());	//得到网络返回的输入流
        }else{
            FileUploadInfo fileUploadInfo = dao.fetch(FileUploadInfo.class, pfid);
            file = new File(fileUploadInfo.getServerPath());
        }

        byte[] buff = new byte[1024];

        try {
            os = response.getOutputStream();
            if (bis==null)
            bis = new BufferedInputStream(new FileInputStream(file));
            int i =0;
            while ((i=bis.read(buff))!=-1){
                os.write(buff,0,i);
                os.flush();
            }

        }catch (Exception e){
            logger.error(e.getMessage(),e);
        }finally {
            try{
                bis.close();
            }catch (Exception e){
                logger.error(e.getMessage(),e);

            }
        }



    }

    @RequestMapping("/listByVersion")
    public Object listByVersion(Long orgId){

        try{
            List<HyDrawing> hyDrawing = dao.query(HyDrawing.class, Cnd.where("org_id", "=", orgId).and("latest","=",false));
            hyDrawing.sort((item1, item2)-> CompareUtil.compareByInt(item1.getVersion(),item2.getVersion()));
            hyDrawing.forEach(item->{
                dao.fetchLinks(item,null);
            });

            return Result.success("success",hyDrawing);
        }catch (Exception e){
            logger.error(e.getMessage(),e);
            return Result.error("fail","服务器内部错误!");
        }


    }

    // 新版本上传
    @RequestMapping("/uploadNew")
    public Object uploadNew(MultipartFile[] file,HttpServletRequest request,Long orgId){

        HyUserInfo user = (HyUserInfo) request.getSession().getAttribute("userInfo");
        try{
            //List<TempFile> tempFiles = getTempFile(file);
            List<PersistFile> persistFiles = getPersistFile(file);

            String absolutePath = persistFiles.get(0).getFile().getAbsolutePath();

            HyDrawing latest = dao.query(HyDrawing.class, Cnd.where("org_id","=",orgId)).stream().filter(item->item.getLatest()).findFirst().get();
            latest.setLatest(false);
            dao.update(latest);

            FileUploadInfo fileUploadInfo = new FileUploadInfo();
            fileUploadInfo.setServerPath(absolutePath);
            fileUploadInfo.setExName(StringUtil.suffix(file[0]));
            fileUploadInfo = dao.insert(fileUploadInfo);
            String imgUrl = IMG_URL+fileUploadInfo.getId();


            HyDrawing hyDrawing = new HyDrawing();
            hyDrawing.setOrgId(orgId);
            hyDrawing.setLatest(true);
            hyDrawing.setVersion(latest.getVersion()+1);
            hyDrawing.setFileName(latest.getFileName());
            hyDrawing.setPngHeight(latest.getPngHeight());
            hyDrawing.setPngWidth(latest.getPngWidth());
            hyDrawing.setProjectFlowChildrenNodeId(latest.getProjectFlowChildrenNodeId());
            hyDrawing.setFlowMapModelId(latest.getFlowMapModelId());
            hyDrawing.setPfid(fileUploadInfo.getId());
            hyDrawing.setStatus(1);
            hyDrawing.setFilePath(imgUrl);
        //    hyDrawing.setFilePath(latest.getFilePath());
            hyDrawing.setHyUserInfoId(user.getId());
            hyDrawing.setProjectId(user.getHyProjectInfoId());
            hyDrawing = dao.insert(hyDrawing);

            hyDrawing.setLocation(latest.getLocation());
            dao.update(hyDrawing);
            Map<String,Object> map = new HashMap<>();

            map.put("ID",hyDrawing.getId());
            map.put("FILE",absolutePath);
            pdfConverImage.toJpgQueue().put(map);
            // 复制旧图纸的标注到新的项目下 ，
            markFileReService.copyOldVersionMarksToNew(latest.getId(),hyDrawing.getId());
            return Result.success("success","操作成功!");
        }catch (Exception e){
            logger.error(e.getMessage(),e);
            return Result.error("fail","服务器内部错误!");
        }



    }


    @RequestMapping("/uploadTmp")
    public Object uploadTmp(MultipartFile[] file,Long markId,HttpServletRequest request){
        String projectId = (String)request.getSession().getAttribute("projectId");
        List<Map> result = new ArrayList<>();
        List<TempFile> tempFiles = getTempFile(file);

        try {
            Map<String, Object> upload = fileUploadService.upload_(tempFiles.get(0).getFile().getAbsolutePath());
            String filePath = (String) upload.get("filePath");
            String extName = (String) upload.get("extName");
            Attachment attachment = new Attachment();
            attachment.setExName(extName);
            attachment.setMarkId(markId);
            attachment.setServerPath(filePath);
            attachment.setName(tempFiles.get(0).getOrgFileName());
            if (markId!=null){
                attachment.setType(AttachmentType.MARK);
            }else {
                attachment.setType(AttachmentType.REVIEW);
            }


            attachment.setProjectInfoId(projectId);

            dao.insert(attachment);
            return Result.success("success","操作成功!");

        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            return Result.error("fail","服务器内部错误!");
        }

    }


    @RequestMapping("/pageShowFile_")
    @ResponseBody
    public void pageShowFile_(HttpServletRequest request, HttpServletResponse response, Long id) {
        InputStream in = null;
        OutputStream out = null;
        Long fid = dao.fetch(HyDrawing.class,id).getFid();

        try {
            FileUploadInfo fileUploadInfo = dao.fetch(FileUploadInfo.class, fid);
            if (fileUploadInfo != null) {
                response.reset();
                response.setHeader("Content-Disposition", "");
                response.setHeader("Pragma", "No-cache");
                response.setHeader("Cache-Control", "No-cache");
                response.setDateHeader("Expires", 0);
                // 创建读取文件的流
                in = new FileInputStream(fileUploadInfo.getServerPath());
                // 创建输出文件的流，也就是response的OutputStream
                out = response.getOutputStream();

                byte[] buffer = new byte[1024];
                int len = 0;
                while ((len = in.read(buffer)) > 0) {
                    out.write(buffer, 0, len);
                }
                out.flush();
            }

        } catch (Exception e) {
            logger.info("error**********"+id);
            logger.error(e.getMessage(), e);
        } finally {
            try {
                if (in != null)
                    in.close();
                if (out != null)
                    out.close();
            } catch (Exception e) {

            }
        }
    }
    @RequestMapping("/pageShowPdf")
    @ResponseBody
    public void pageShowPdf(HttpServletRequest request, HttpServletResponse response, Long fid) {
        InputStream in = null;
        OutputStream out = null;
        try {
            FileUploadInfo fileUploadInfo = dao.fetch(FileUploadInfo.class, fid);
            if (fileUploadInfo != null) {
                response.reset();
                response.setContentType("application/pdf");
                response.setHeader("Content-Disposition", "");
                response.setHeader("Pragma", "No-cache");
                response.setHeader("Cache-Control", "No-cache");
                response.setDateHeader("Expires", 0);
                // 创建读取文件的流
                in = new FileInputStream(fileUploadInfo.getServerPath());
                // 创建输出文件的流，也就是response的OutputStream
                out = response.getOutputStream();

                byte[] buffer = new byte[1024];
                int len = 0;
                while ((len = in.read(buffer)) > 0) {
                    out.write(buffer, 0, len);
                }
                out.flush();
            }

        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            try {
                if (in != null)
                    in.close();
                if (out != null)
                    out.close();
            } catch (Exception e) {

            }
        }
    }

    @RequestMapping("/pageShowFile")
    @ResponseBody
    public void pageShowFile(HttpServletRequest request, HttpServletResponse response, Long fid) {
        InputStream in = null;
        OutputStream out = null;
        try {
            FileUploadInfo fileUploadInfo = dao.fetch(FileUploadInfo.class, fid);
            if (fileUploadInfo != null) {
                response.reset();
                response.setHeader("Content-Disposition", "");
                response.setHeader("Pragma", "No-cache");
                response.setHeader("Cache-Control", "No-cache");
                response.setDateHeader("Expires", 0);
                // 创建读取文件的流
                in = new FileInputStream(fileUploadInfo.getServerPath());
                // 创建输出文件的流，也就是response的OutputStream
                out = response.getOutputStream();

                byte[] buffer = new byte[1024];
                int len = 0;
                while ((len = in.read(buffer)) > 0) {
                    out.write(buffer, 0, len);
                }
                out.flush();
            }

        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            try {
                if (in != null)
                    in.close();
                if (out != null)
                    out.close();
            } catch (Exception e) {

            }
        }
    }


    @RequestMapping("/pageShowFileUrl")
    @ResponseBody
    public Object pageShowFile(HttpServletRequest request, HttpServletResponse response, String imgUrl, String fileId, String fileName,String flowMapModelId) {


        InputStream in = null;
        OutputStream out = null;
        FileUploadInfo fileUploadInfo = null;
        String projectFlowChildrenNodeId = (String)request.getSession().getAttribute("projectFlowChildrenNodeId");
        projectFlowChildrenNodeId= StringUtil.isEmpty(projectFlowChildrenNodeId)?"40bb06b765144d0cbbdc314dc540d0dd":projectFlowChildrenNodeId;

        try {
            // 1. 查找数据库中是否存在该文件

            HyDrawing hyDrawing = dao.fetch(HyDrawing.class, Cnd.where("fileId", "=", fileId));

            if (hyDrawing == null) {
                // 说明该文件未参与转换  开始文件转换流程
                Map<String, Object> fileInfo = fileUploadService.upload(imgUrl);
                String filePath = (String) fileInfo.get("filePath");
                Map<String, Object> jpgInfo = fileUploadService.pdf2jpg(filePath);
                String jpgPath = (String) jpgInfo.get("jpgPath");
                String exName = (String) jpgInfo.get("exName");
                Integer width = (Integer) jpgInfo.get("width");
                Integer height = (Integer) jpgInfo.get("height");
                fileUploadInfo = new FileUploadInfo();
                fileUploadInfo.setExName(exName);
                fileUploadInfo.setServerPath(jpgPath);
                fileUploadInfo = dao.insert(fileUploadInfo);

                int random = (int) (1 + Math.random() * (100));
                hyDrawing = new HyDrawing();
                hyDrawing.setFid(fileUploadInfo.getId());
                hyDrawing.setFileId(fileId);
                hyDrawing.setFileName(fileName);
                hyDrawing.setFilePath(imgUrl);
                hyDrawing.setPngHeight(height);
                hyDrawing.setPngWidth(width);
                hyDrawing.setFlowMapModelId(flowMapModelId);
                hyDrawing.setProjectFlowChildrenNodeId(projectFlowChildrenNodeId);
                hyDrawing.setStatus(2);
                hyDrawing.setOpinionCount(random);
                hyDrawing = dao.insert(hyDrawing);



            } else {

                fileUploadInfo = dao.fetch(FileUploadInfo.class, hyDrawing.getFid());

            }

            return Result.success("success", hyDrawing);

        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return Result.error("fail",e.getMessage());

        }
    }





    /**
     * 上传并获取临时文件
     * @param files
     * @return
     */
    public List<TempFile> getTempFile(MultipartFile[] files) {
        List<TempFile> tempFiles = new ArrayList<>();
        try {
            for (MultipartFile mfile : files) {
                byte[] bytes = mfile.getBytes();
                // 获取文件后缀名
                String suffix = StringUtil.suffix(mfile);
                // 获取文件名称
                String filename =StringUtil.getOriginalFilename(mfile);


                File file = tempFilePool.createFile(suffix);

                OutputStream out = new FileOutputStream(file);
                out.write(bytes);
                out.flush();
                out.close();
                tempFiles.add(new TempFile(file,filename));
            }
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        }
        return tempFiles;
    }

    /**
     * 上传并获取持久化文件
     * @param files
     * @param suffix
     * @return
     */
    public List<PersistFile> getPersistFile(MultipartFile[] files) {
        List<PersistFile> persistFiles = new ArrayList<>();
        try {
            for (MultipartFile mfile : files) {
                byte[] bytes = mfile.getBytes();
                // 获取文件后缀名
                String suffix = StringUtil.suffix(mfile);
                // 获取文件名称
                String filename =StringUtil.getOriginalFilename(mfile);
                String filePath = fileUploadService.getPath();
                filePath+= R.UU16()+suffix;

                    File file = Files.createFileIfNoExists(filePath);

                OutputStream out = new FileOutputStream(file);
                out.write(bytes);
                out.flush();
                out.close();
                persistFiles.add(new PersistFile(file,filename));
            }
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        }
        return persistFiles;
    }

}



